package cz.acies.organizer.data.process;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import cz.acies.data.DBConnector;
import cz.acies.data.persist.ModelObject;
import cz.acies.data.persist.TreeNode;
import cz.acies.data.process.AbstractProcessor;
import cz.acies.organizer.data.dao.CalendarTaskDAO;
import cz.acies.organizer.data.persist.CalendarTask;
import cz.acies.uniql.metadata.DBMetaData;
import cz.acies.uniql.metadata.FieldMetaData;
import cz.acies.uniql.metadata.TableMetaData;
import cz.acies.uniql.sql.element.UniQLCondition;
import cz.acies.uniql.sql.element.UniQLWhere;
import cz.acies.utils.DateUtils;
import cz.acies.utils.UIDGenerator;

public class CalendarProcessor extends AbstractProcessor
{
	private String[] datePatterns = {
		"yyyy-MM-dd'T'HH:mm:ss'Z'",
		"yyyy-MM-dd HH:mm:ss",
		"d.M.yyyy H:mm",
	};

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		super.execute(request, response);
	}

	@Override
	public String execute(Map<String, Object> params) {
		String data = "";
		String processId = params.containsKey("processId") ? (String) params.get("processId") : "UNKNOW";
		//System.out.println("processId = "+processId);
		if (processId.equals("selectCurrentMonth")) {
			data = selectCurrentMonth();
		} else if (processId.equals("selectMonth")) {
			data = selectMonth(params);
		} else if (processId.equals("doAppend")) {
			//System.out.println("doAppend: " + params);
			data = doAppend(params);
		} else if (processId.equals("doUpdate")) {
			//System.out.println("doUpdate: " + params);
			data = doUpdate(params);
		} else if (processId.equals("doDelete")) {
			data = doDelete(params);
		} else {
			data = "UNKNOW";
		}
		return data;
	}

	public String createFolders(Map<String, Object> params)  {
		String data = "";
		try {
			TreeNode root = new TreeNode("CA.F.00000000000ROOT","Kalendář");
			root.setAttribute("selectable", false);
			List<TreeNode> list = new ArrayList<TreeNode>();
			list.add(root);
			Gson gson = new Gson(); 
			data = gson.toJson(list);
			//System.out.println("treeData: " + data);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}

	public String selectMonth(Map<String, Object> params) {
		String data = "";
		try {
			String dateFrom = (String) params.get("dateFrom");
			String dateTo = (String) params.get("dateTo");
			
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			
			CalendarTaskDAO dao = new CalendarTaskDAO();
			Calendar today = Calendar.getInstance(); 
			UniQLWhere where = new UniQLWhere();
			where.add(new UniQLCondition("dateStart", ">=", "'"+DateUtils.firstDayOfMonth(DateUtils.addMonth(today, -1))+"'"), "AND");
			where.add(new UniQLCondition("dateStart", "<=", "'"+DateUtils.lastDayOfMonth(DateUtils.addMonth(today, 1))+"'"));			
			List<ModelObject> events = dao.selectByWhere("calendar_task", where, CalendarTask.class);
			
			for (ModelObject obj : events) {
				CalendarTask event = (CalendarTask) obj;
				Map<String, Object> point = event2json(event);
				list.add(point);
			}
			
			Gson gson = new Gson();
			data = gson.toJson(list);
			//System.out.println("selectCurrentMonth: "+data);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}

	public String selectCurrentMonth() {
		String data = "";
		try {
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			
			CalendarTaskDAO dao = new CalendarTaskDAO();
			Calendar today = Calendar.getInstance(); 
			UniQLWhere where = new UniQLWhere();
			where.add(new UniQLCondition("dateStart", ">=", "'"+DateUtils.firstDayOfMonth(DateUtils.addMonth(today, -1))+"'"), "AND");
			where.add(new UniQLCondition("dateStart", "<=", "'"+DateUtils.lastDayOfMonth(DateUtils.addMonth(today, 1))+"'"));			
			List<ModelObject> events = dao.selectByWhere("calendar_task", where, CalendarTask.class);
			
			for (ModelObject obj : events) {
				CalendarTask event = (CalendarTask) obj;
				Map<String, Object> point = event2json(event);
				list.add(point);
			}
			
			Gson gson = new Gson();
			data = gson.toJson(list);
			System.out.println("selectCurrentMonth: "+data);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}
	
	private Map<String, Object> event2json(CalendarTask event) {
		Map<String, Object> data = new LinkedHashMap<String, Object>();
		
		data.put("id", event.getId());
		data.put("subject", event.getSubject());
		data.put("dateStart", DateFormatUtils.format(event.getDateStart(), "yyyy-MM-dd HH:mm"));
		data.put("dateEnd", DateFormatUtils.format(event.getDateEnd(), "yyyy-MM-dd HH:mm"));
		data.put("allDay", event.isAllDay());
		data.put("description", event.getDescription());
		data.put("recRule", event.getRecRule());
		//data.put("color", "green");
		//data.put("textColor", "black");
		
		//'repeat_i' => $input->repeat_int,
		//'repeat_f' => $input->repeat_freq,
		//'repeat_e' => $input->repeat_end
		return data;
	}
	
	public String doAppend(Map<String, Object> params) {
		String data = "";
		try {
			System.out.println("CalendarProcessor.doAppend("+params+")");
			String models = (String) params.get("models");
			GsonBuilder builder = new GsonBuilder();
		    builder.serializeNulls();
		    TypeToken<List<Map<String, Object>>> typeOfT = new TypeToken<List<Map<String, Object>>>() {
		    };
    		Gson gson = builder.create();
			
			List<Map<String, Object>> events = gson.fromJson(models, typeOfT.getType());
			if (events != null && !events.isEmpty()) {
				Map<String, Object> event = (Map<String, Object>)events.get(0);
				//CalendarProcessor.doAppend({models=[{"startTimezone":"","endTimezone":"","recurrenceRule":"FREQ=MONTHLY;COUNT=5;BYDAY=1WE","recurrenceException":"","description":"","atendees":null,"id":"","subject":"pok2","dateStart":"2014-02-12T07:00:00Z","dateEnd":"2014-02-12T07:30:00Z","allDay":false}], processId=doAppend})
				String id = UIDGenerator.createUID("CA.E");
				CalendarTask record = new CalendarTask(id);
				
				//"start":"2013-12-01T01:00:00.000Z",
				//"startTimezone":"",
				String dateStart = (String) event.get("dateStart");
				java.util.Date dtStart = org.apache.commons.lang3.time.DateUtils.parseDate(dateStart, "yyyy-MM-dd'T'HH:mm:ss'Z'");
				record.setDateStart(new Timestamp(dtStart.getTime()));
				
				//"end":"2013-12-01T02:00:00.000Z",
				//"endTimezone":"",
				String dateEnd = (String) event.get("dateEnd");
				java.util.Date dtEnd = org.apache.commons.lang3.time.DateUtils.parseDate(dateEnd, "yyyy-MM-dd'T'HH:mm:ss'Z'");
				record.setDateEnd(new Timestamp(dtEnd.getTime()));
	
				record.setDuration("");
				record.setCategories("");
				
				//"title":"pokus",
				record.setSubject((String) event.get("subject"));
				record.setLocation((String) event.get("location"));
				//"description":"yxcvbn",
				record.setDescription((String) event.get("description"));
				
				boolean allDay = (Boolean) event.get("allDay");
				record.setAllDay(allDay);
	
				String recRule = (String) event.get("recRule");
				record.setRecRule(recRule);
				
				//"recurrenceRule":"",
				//"recurrenceException":"",
				/*
				{models=[{
					"title":"recor",
					"start":"2013-12-03T23:00:00.000Z",
					"startTimezone":"",
					"end":"2013-12-04T23:00:00.000Z",
					"endTimezone":"",
					"recurrenceRule":"FREQ=DAILY;COUNT=3",
					"recurrenceException":"",
					"description":"",
					"atendees":null,
					"id":"",
					"allDay":false}], 
				*/
				record.setUserId("WX.R.AEFBE4JE41ZYBEM");
	
				CalendarTaskDAO dao = new CalendarTaskDAO();
				dao.doAppend(record);
				
				List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
				Map<String, Object> point = event2json(record);
				gson = new Gson();
				data = gson.toJson(list);
			}
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}

	
	public String doUpdate(Map<String, Object> params) {
		String data = "";
		try {
			System.out.println("CalendarProcessor.doUpdate("+params+")");
			DBMetaData dbmd = DBConnector.instance().dbmd();
			TableMetaData tmd = dbmd.getTable("calendar_task");
			
			System.out.println("CalendarProcessor.doUpdate(): "+params);
			
			String models = (String) params.get("models");
			GsonBuilder builder = new GsonBuilder();
		    builder.serializeNulls();
		    TypeToken<List<Map<String, Object>>> typeOfT = new TypeToken<List<Map<String, Object>>>() {
		    };
    		Gson gson = builder.create();
			
			List<Map<String, Object>> events = gson.fromJson(models, typeOfT.getType());
			String id = "";
			if (!events.isEmpty()) {
				Map<String, Object> event = (Map<String, Object>)events.get(0);
				CalendarTaskDAO dao = new CalendarTaskDAO();
				id = (event.containsKey("id")) ? ""+event.get("id") : "";
				if (id.startsWith("CA.E.")) {
					CalendarTask record = dao.selectRecordById(id);
					String dateStart = (String) event.get("dateStart");
					record.setDateStart(new Timestamp(DateUtils.parseDate(dateStart, datePatterns).getTime()));
					String dateEnd = (String) event.get("dateEnd");
					record.setDateStart(new Timestamp(DateUtils.parseDate(dateEnd, datePatterns).getTime()));
					String recRule = (String) event.get("recRule");
					record.setRecRule(recRule);
					
					dao.doUpdate(record);
					
					List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
					Map<String, Object> point = event2json(record);
					gson = new Gson();
					//data = gson.toJson(list);
					data = "callback()";
				} else {
					
				}
			} else {
				
			}

			/*
			if (id.startsWith("CA.E.")) {
				List<ModelObject> records = dao.selectById("calendar_task", id, CalendarTask.class);
				if (!records.isEmpty()) {
					CalendarTask record = (CalendarTask) records.get(0);
					Map<String, Object> map = new LinkedHashMap<String, Object>();
					for (Map.Entry<String, Object> e : params.entrySet()) {
						String key = e.getKey();
						FieldMetaData fmd = tmd.getFieldByName(key);
						if (key.equals("dateStart")) {
							String dateStart = (String) params.get("dateStart");
							java.util.Date dtStart = null;
							try {
								dtStart = org.apache.commons.lang3.time.DateUtils.parseDate(dateStart, "d.M.yyyy H:mm");
							} catch (Exception exc) {
								dtStart = org.apache.commons.lang3.time.DateUtils.parseDate(dateStart, "yyyy-MM-dd HH:mm:ss");
							}
							//record.setDateStart(new Timestamp(dtStart.getTime()));
							map.put(key, new Timestamp(dtStart.getTime()));
						} else if (key.equals("dateEnd")) {
							String dateEnd = (String) params.get("dateEnd");
							java.util.Date dtEnd = null;
							try {
								dtEnd = org.apache.commons.lang3.time.DateUtils.parseDate(dateEnd, "d.M.yyyy H:mm");
							} catch (Exception exc) {
								dtEnd = org.apache.commons.lang3.time.DateUtils.parseDate(dateEnd, "yyyy-MM-dd HH:mm:ss");
							}
							System.out.println("dtEnd: " + dtEnd);
							//record.setDateEnd(new Timestamp(dtEnd.getTime()));
							map.put(key, new Timestamp(dtEnd.getTime()));
						} else if (key.equals("allDayEvent")) {
							boolean allDay = params.containsKey("allDayEvent") && params.get("allDayEvent").equals("1");
							map.put(key, allDay);
						} else if (fmd != null) {
							map.put(key, params.get(key));
						}
					}
					record.setEditorId("WX.R.AEFBE4JE41ZYBEM");
					BeanUtils.populate(record, map);
					dao.doUpdate(record);				
				}
			} else {
				//CalendarTask record = new CalendarTask();
				//record.setId(id);
			}
			*/
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}
	
	public String doDelete(Map<String, Object> params) {
		String data = "";
		try {
			//System.out.println("doDelete:"+params);
			String models = (String) params.get("models");
			GsonBuilder builder = new GsonBuilder();
		    builder.serializeNulls();
		    TypeToken<Map<String, Object>> typeOfT = new TypeToken<Map<String, Object>>() {
		    };
    		Gson gson = builder.create();
			
			Map<String, Object> mdata = gson.fromJson(models, typeOfT.getType());

			String uid = (String) mdata.get("uid");
			CalendarTaskDAO dao = new CalendarTaskDAO();
			CalendarTask record = new CalendarTask(uid);
			dao.doDelete(record);
			data = "[]";
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}
}